package com.tbit.uqbike.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.UserOpLog;
import com.tbit.manager.api.dto.GiftCardUserDTO;
import com.tbit.uqbike.constant.RedisKeyConstant;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.GiftCardUserService;
import com.tbit.uqbike.service.business.UserAccountLogService;
import com.tbit.uqbike.service.business.UserService;
import com.tbit.uqbike.webmanager.business.user_op_log.service.UserOpLogService;
import com.tbit.uqbike.webmanager.dao.capital.BalanceChangeDao;
import com.tbit.uqbike.webmanager.dao.capital.UserCapitalChangeDao;
import com.tbit.uqbike.webmanager.dao.core.GiftCardUserDao;
import com.tbit.uqbike.webmanager.dao.core.UserAccountMoneyDao;
import com.tbit.uqbike.webmanager.dao.capital.MoneyOpeLogDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chenmengran
 * @Description: 用户礼品卡使用情况
 * @date 2020\1\4 000413:57
 */
@Service
public class GiftCardUserServiceImpl implements GiftCardUserService {
    @Autowired
    private GiftCardUserDao giftCardUserDao;
    @Autowired
    private UserAccountLogService userAccountLogService;
    @Autowired
    private UserService userService;
    @Autowired
    private MoneyOpeLogDao moneyOpeLogDao;
    @Autowired
    private BalanceChangeDao balanceChangeDao;
    @Autowired
    private UserCapitalChangeDao userCapitalChangeDao;
    @Autowired
    private UserAccountMoneyDao userAccountMoneyDao;
    @Resource
    private RedisService redisService;
    @Autowired
    private UserOpLogService userOpLogService;

    @Override
    public GiftCardUser getByUser(Integer accountId, Integer userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("userId", userId);

        return giftCardUserDao.getByUser(params);
    }

    @Override
    public void add(Integer accountId, Integer userId, Integer money) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("userId", userId);
        params.put("money", money);
        params.put("updateTime", new Date());

        giftCardUserDao.insert(params);
    }

    @Override
    public void updateMoney(Integer accountId, Integer userId, Integer money) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("userId", userId);
        params.put("money", money);
        params.put("updateTime", new Date());

        giftCardUserDao.updateMoney(params);
    }

    @Override
    public void recharge(Integer accountId, Integer userId, Integer money, String remark, LoginInfo loginInfo) {
        /**查询用户信息*/
        User user = userService.getByUserId(userId);
        if (user == null) {
            throw new BaseException("user_not_exist");
        }
        boolean locked = redisService.locked(RedisKeyConstant.format(RedisKeyConstant.GIFT_CARD_BALANCE_UPDATE_KEY, userId), 5);
        if (locked) {
            throw new BaseException("数据已提交，请勿重复请求");
        }
        /**如果是扣费，判断礼品卡金额是否小于0*/
        GiftCardUser giftCardUser = getByUser(accountId, userId);
        //用户区域余额
        UserAccountMoney userAccountMoney = userAccountMoneyDao.selectOne(new QueryWrapper<UserAccountMoney>().eq("userId", userId).eq("accountId", accountId).eq("moneyType", 3));
        Long userAccountGiftCardMoney = userAccountMoney == null ? 0L : userAccountMoney.getMoney();
        Long changeStartMoney = giftCardUser == null ? 0L : giftCardUser.getMoney().longValue();
        Long changeEndMoney = changeStartMoney + money;
        if (!changeStartMoney.equals(userAccountGiftCardMoney)) {
            throw new BaseException("用户区域礼品卡数据有误,请联系管理员处理");
        }
        //这里是分
        int giftCardMoneyTop = 10000000;
        if (giftCardUser == null) {
            if (money < 0) {
                throw new BaseException("礼品卡余额不能小于0");
            }
            if (money > giftCardMoneyTop) {
                throw new BaseException("业务风控拦截: 礼品卡余额已超限。最大值为10万元");
            }
            /**添加*/
            add(accountId, userId, money);
        } else {
            boolean lessThanZero = giftCardUser.getMoney() < 0;
            if ((giftCardUser.getMoney() + money) < 0) {
                if (lessThanZero) {
                    throw new BaseException("礼品卡余额已低于0元，无法继续扣款");
                } else {
                    throw new BaseException("您输入的扣除金额大于余额，请重新输入");
                }
            }
            if ((giftCardUser.getMoney() + money) > giftCardMoneyTop) {
                throw new BaseException("业务风控拦截: 礼品卡余额已超限。最大值为10万元");
            }
            /**更新金额*/
            updateMoney(accountId, userId, money);
        }
        //手工资金操作记录
        Date operaTime = new Date();
        moneyOpeLogDao.insert(new MoneyOpeLog(accountId, 2, money > 0 ? 1 : 0, money, operaTime, user.getUserId(), user.getPhone(), loginInfo.getAccountUserId(), loginInfo.getPhone(), remark));
        balanceChangeDao.insert(new BalanceChange(null, userId, user.getPhone(), user.getName(), accountId, user.getAccountId(), changeStartMoney, (long) Math.abs(money), changeEndMoney, money > 0 ? 1 : 2, 3, money > 0 ? 17 : 18, operaTime.getTime(), remark, null));
        userCapitalChangeDao.insert(new UserCapitalChange(null, userId, user.getPhone(), user.getName(), accountId, user.getAccountId(), changeStartMoney, (long) Math.abs(money), changeEndMoney, money > 0 ? 1 : 2, 3, money > 0 ? 17 : 18, null, loginInfo.getAccountUserId(), loginInfo.getPhone(), loginInfo.getName(), null, null, operaTime.getTime(), remark, accountId));
        if (userAccountMoney == null) {
            userAccountMoneyDao.insert(new UserAccountMoney(userId, user.getPhone(), accountId, user.getAccountId(), money.longValue(), operaTime.getTime(), 3, "人工修改礼品卡新增区域礼品卡余额"));
        } else {
            userAccountMoneyDao.update(new UserAccountMoney(userId, user.getPhone(), accountId, user.getAccountId(), userAccountMoney.getMoney() + money.longValue(), operaTime.getTime(), 3, "人工修改礼品卡修改区域礼品卡余额"), new UpdateWrapper<UserAccountMoney>().eq("userId", userId).eq("accountId", accountId).eq("moneyType", 3));
        }
        /**记录日志*/
        UserAccountLog userAccountLog = new UserAccountLog();
        userAccountLog.setAccountId(user.getAccountId());
        userAccountLog.setUserId(userId);
        userAccountLog.setMoneyType(1);//礼品卡余额
        userAccountLog.setType(money < 0 ? 0 : 1);//扣费
        userAccountLog.setMoney(Math.abs(money));
        userAccountLog.setOperaTime(operaTime);
        userAccountLog.setRemark(remark);
        userAccountLogService.insert(userAccountLog);

        // 插入用户操作日志
        userOpLogService.insertSingle(UserOpLog.builder()
                .accountId(user.getAccountId())
                .opUser(loginInfo.getName())
                .opUserPhone(loginInfo.getPhone())
                .targetUser(user.getName())
                .targetUserPhone(user.getPhone())
                .operation("礼品卡变动")
                .opType("修改金额")
                .opPlatform(loginInfo.getLoginUserPlatform())
                .opTime(LocalDateTime.now())
                .detail("变动金额: " + money / 100d + "元")
                .result(true)
                .build());
    }

    @Override
    public GiftCardUserDTO getRechargeMoneyAndGiftMoney(Integer accountId, Integer userId) {
        GiftCardUserDTO giftCardUserDTO = giftCardUserDao.getRechargeMoneyAndGiftMoney(accountId, userId);
        if (giftCardUserDTO == null){
            User user = userService.getByUserId(userId);
            giftCardUserDTO = new GiftCardUserDTO();
            giftCardUserDTO.setMoney(0);
            giftCardUserDTO.setRechargeMoney(user.getMoney());
        }
        return giftCardUserDTO;
    }
}
